package com.example.gyrodemo;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.service.carrier.CarrierMessagingService;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import java.time.LocalDate;
import java.util.ArrayList;

/**
 * @author qjy
 */
public class MainActivity extends AppCompatActivity implements SensorEventListener {

    /** 传感器管理器对象 **/
    private SensorManager sensorManager;
    /** 传感器对象 **/
    private Sensor gyroSensor;
    /** 时间戳 **/
    private float timestamp;
    /** 四元数 **/
    private final float[] quaternion = new float[4];
    /** 纳秒-秒转换常量 **/
    private static final float NS2S = 1.0f / 1000000000.0f;
    /** 微秒-秒转换常量 **/
    private static final float US2S = 1.0f / 1000000.0f;
    /** 设定采样率（μs） **/
    public static final int SAMPLINGPERIODUS = 2400;
    /** padding_x 距离屏幕左侧的距离 **/
    private static float padding_x = 0;
    /** padding_y 距离屏幕上方的距离 **/
    private static float padding_y = 0;
    /** 屏幕高度 **/
    private int winHeight;
    /** 屏幕宽度 **/
    private int winWidth;
    /** 图标 **/
    private ImageView img;
    /** Activity Tag **/
    private static final String TAG = "MainActivity";
    /** tv对象：x轴角速度 **/
    private TextView tv_omgX;
    /** tv对象：y轴角速度 **/
    private TextView tv_omgY;
    /** tv对象：x轴转角 **/
    private TextView tv_theta_x;
    /** tv对象：x轴转角 **/
    private TextView tv_theta_y;
    /** GyroDataProcess **/
    private GyroDataProcessing GDP;
    /** Button to Start Smooth **/
    private Button smoothBtn;
    /** Button State **/
    private boolean smoothBtnState;
    /** ArrayList to store sensor data **/
    private ArrayList<Double> resultDeltaTheta;
    /** Exponential smoothing parameter **/
    private static double ALPHA = 0;
    /** SeekBar for Smooth ALpha **/
    private SeekBar seekBar;
    /** To Show the Num of Alpha**/
    private TextView seekBar_tv;
    /** BroadcastReceiver for BatteryLevel **/
    private BatteryLeverlReceiver batteryLeverlReceiver;
    /** 状态栏statusBar Height **/
    private int statusBarHeight;
    /** ActonBar Height**/
    private int actionBarHeight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initSensor();
        initClickEvent();
        initSeekBarListener();
        registerBatteryReceiver();
        initData();
    }
    /**
     * initView 获取View相关属性
     * @return void
     */
    private void initView() {
        // 获取textview对象
        tv_omgX = this.findViewById(R.id.omg_x);
        tv_omgY = findViewById(R.id.omg_y);
        tv_theta_x = findViewById(R.id.theta_x);
        tv_theta_y = findViewById(R.id.theta_y);
        seekBar_tv = this.findViewById(R.id.seekbar_tv);

        // 获取imgview
        img = findViewById(R.id.img_ball);

        // 获取button
        smoothBtn = this.findViewById(R.id.smooth_btn);

        // 获取seekbar
        seekBar = this.findViewById(R.id.seekbar);

        //  获取高宽属性
        winWidth = getBarsHeight.getScreenWidth(this);
        winHeight = getBarsHeight.getScreenHeight(this);
        statusBarHeight = getBarsHeight.getStatusBarHeight(this);
        actionBarHeight = getBarsHeight.getActionBarHeight(this);
    }
    /**
     * initSensor 初始化SensorManager、Sensor对象
     * @return void
     */
    private void initSensor() {
        // 获取传感器管理器
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        // 获取传感器 and 判断是否获取成功
        gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        //  dataProcess对象
        GDP = new GyroDataProcessing();

        if (gyroSensor == null) {
            Toast.makeText(this,"获取 陀螺仪失败 ...", Toast.LENGTH_LONG).show();
            Log.e(TAG, "onCreate: 未找到陀螺仪");
            finish();
        }
    }
    /**
     * registerGyro 注册陀螺仪
     * @return void
     */
    private void registerGyro() {
        if (!sensorManager.registerListener(this, gyroSensor, SAMPLINGPERIODUS)) {
            Toast.makeText(this,"注册陀螺仪失败 ...", Toast.LENGTH_LONG).show();
            Log.e(TAG, "onResume: 注册陀螺仪失败...");
            finish();
        }
    }

    /**
     * unregisterSensor 注销陀螺仪监听
     * @return void
     */
    private void unregisterSensor() {
        sensorManager.unregisterListener(this);
    }

    /**
     * initClickEvent 开启平滑按钮监听
     * @return void
     */
    private void initClickEvent() {
        smoothBtnState = false;
        smoothBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (smoothBtnState) {
                    smoothBtnState = false;
                    smoothBtn.setText("Touch to open smooth");

                } else {
                    smoothBtnState = true;
                    smoothBtn.setText("Touch to close smooth");
                }
            }
        });
    }

    /**
     * initSeekBarListener seekBar监听
     * @return void
     */
    private void initSeekBarListener() {
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (smoothBtnState) {
                    ALPHA = (double) (progress / 100.0) * 1.0;
                    seekBar_tv.setText("value : " + ALPHA);
                    GDP.setAlpha(ALPHA);
                } else {
                    MyToast.showToast(MainActivity.this, "Please Touch TO Open Smooth !");
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

    /**
     * registerBatteryReceiver 注册低电量广播接收
     * @return void
     */
    private void registerBatteryReceiver() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
        batteryLeverlReceiver = new BatteryLeverlReceiver();
        this.registerReceiver(batteryLeverlReceiver, intentFilter);
    }

    /**
     * unregisterBroadcastReceiver 注销广播接收
     * @return void
     */
    private void unregisterBroadcastReceiver() {
        if (batteryLeverlReceiver != null) {
            this.unregisterReceiver(batteryLeverlReceiver);
            batteryLeverlReceiver = null;
            Log.d(TAG, "unregister receiver...");
        }
    }

    /**
     * initData 初始化data buffer
     * @return void
     */
    private void initData() {
        resultDeltaTheta = new ArrayList<Double>(2);
        resultDeltaTheta.add(0.0);
        resultDeltaTheta.add(0.0);
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerGyro();
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterSensor();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterBroadcastReceiver();
    }

    @SuppressLint("DefaultLocale")
    @Override
    public void onSensorChanged(SensorEvent event) {
        // 当传感器数据发生变化时，触发当前回调函数；
        if (timestamp != 0) {
            // 计算两次事件事件的 间隔时间
            float dt = SAMPLINGPERIODUS * US2S;

            // 获取三个轴的角速度
            float omgX = event.values[0];
            float omgY = event.values[1];

            //  计算两次event之间的转角
            float deltaThetaX =  omgX * dt;
            float deltaThetaY =  omgY * dt;

            // 显示实时数据
            setDataofView(omgX, omgY, deltaThetaX, deltaThetaY);

            //  修正图标位置
            modifyPosition(deltaThetaX, deltaThetaY);
        }
        // 更新timestamp
        timestamp = event.timestamp;
    }

    /**
     * setDataofView set view中Sensor data
     *
     * @param omgX 角速度x-axis
     * @param omgY 角速度y-axis
     * @param deltaThetaX 角度变化量x
     * @param deltaThetaY 角度变化量y
     * @return void
     */
    private void setDataofView(float omgX, float omgY, float deltaThetaX, float deltaThetaY) {
        //  设置4个text中的数值
        tv_omgX.setText(String.format("%f", omgX));
        tv_omgY.setText(String.format("%f", omgY));
        tv_theta_x.setText(String.format("%f", deltaThetaX));
        tv_theta_y.setText(String.format("%f", deltaThetaY));
    }

    /**
     * modifyPosition修改图标位置
     *
     * @param deltaThetaY X方向变化量
     * @param deltaThetaY Y方向变化量
     * @return void
     */
    private void modifyPosition(double deltaThetaX, double deltaThetaY) {

        resultDeltaTheta.set(0, deltaThetaX);
        resultDeltaTheta.set(1, deltaThetaY);
        //  数据平滑
        if (smoothBtnState) {
            GDP.firOrdexpSmoothing(deltaThetaX, deltaThetaY);
            resultDeltaTheta.set(0, GDP.getXl());
            resultDeltaTheta.set(1, GDP.getYl());
        }

        padding_y += resultDeltaTheta.get(0) * 1200;
        padding_x += resultDeltaTheta.get(1) * 1000;
        
        if (padding_x < 0) {
            padding_x = 0;
        } else if (padding_x >= winWidth- img.getWidth()) {
            padding_x = winWidth- img.getWidth() ;
        }

        if (padding_y < 0) {
            padding_y = 0;
        } else if (padding_y >= (winHeight- img.getHeight() - actionBarHeight)) {
            padding_y = winHeight- img.getHeight() - actionBarHeight;
        }
        img.setTranslationX(padding_x);
        img.setTranslationY(padding_y);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}